﻿namespace Known.Blazor;

public class BaseLayout : LayoutComponentBase
{
    [Inject] protected IAuthStateProvider AuthProvider { get; set; }
    [Inject] public NavigationManager Navigation { get; set; }
    [Inject] public IServiceScopeFactory Factory { get; set; }
    [Inject] public JSService JS { get; set; }
    [Inject] public IUIService UI { get; set; }
    [CascadingParameter] public UIContext Context { get; set; }
    public Language Language => Context?.Language;
    public MenuInfo CurrentMenu => Context?.Current;
    protected IAuthService AuthService { get; private set; }
    internal ISystemService SystemService { get; private set; }

    protected override async Task OnInitializedAsync()
    {
        try
        {
            await base.OnInitializedAsync();
            AuthService = await CreateServiceAsync<IAuthService>();
            SystemService = await CreateServiceAsync<ISystemService>();
            UI.Language = Language;
            Context.UI = UI;
            if (Context.System == null)
                Context.System = await SystemService.GetSystemAsync();
            await OnInitAsync();
        }
        catch (Exception ex)
        {
            await OnError(ex);
        }
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender)
        {
            //JS不能在初始化中调用
            if (Config.App.IsSize)
            {
                var size = await JS.GetCurrentSizeAsync();
                if (string.IsNullOrWhiteSpace(size))
                    size = Context.UserSetting.Size;
                if (string.IsNullOrWhiteSpace(size))
                    size = Config.App.DefaultSize;
                await JS.SetCurrentSizeAsync(size);
            }
            if (Config.App.IsLanguage)
            {
                var language = await JS.GetCurrentLanguageAsync();
                if (string.IsNullOrWhiteSpace(language))
                    language = Context.UserSetting.Language;
                Context.CurrentLanguage = language;
            }
            if (Config.App.IsTheme)
                Context.Theme = await JS.GetCurrentThemeAsync();
        }
    }

    protected virtual Task OnInitAsync() => Task.CompletedTask;

    public Task<T> CreateServiceAsync<T>() where T : IService => Factory.CreateAsync<T>(Context);
    public void NavigateTo(string url) => Navigation.NavigateTo(url);

    public void NavigateTo(MenuInfo item)
    {
        if (item == null)
            return;

        //缓存APP代码中添加的菜单
        UIConfig.SetMenu(item);
        NavigateTo(item.RouteUrl);
    }

    public void Back()
    {
        if (CurrentMenu == null || string.IsNullOrWhiteSpace(CurrentMenu.BackUrl))
            return;

        NavigateTo(CurrentMenu.BackUrl);
    }

    public async Task SignOutAsync()
    {
        var user = await AuthProvider.GetUserAsync();
        var result = await AuthService.SignOutAsync(user?.Token);
        if (result.IsValid)
        {
            Context.SignOut();
            await SetCurrentUserAsync(null);
            NavigateTo("/login");
            Config.OnExit?.Invoke();
        }
    }

    public async Task OnError(Exception ex)
    {
        Logger.Exception(ex);
        await UI.Notice(ex.Message, StyleType.Error);
    }

    public virtual Task ShowSpinAsync(string text, Func<Task> action) => Task.CompletedTask;
    public virtual Task StateChangedAsync() => InvokeAsync(StateHasChanged);

    public async Task SetCurrentUserAsync(UserInfo user)
    {
        if (AuthProvider != null)
            await AuthProvider.SetUserAsync(user);
    }
}